<?php
if(!defined('IN_SONG')) exit('No direct script access allowed');  
/**
 * Class debug
 * 
 * @package         Kernel
 * @subpackage      Debug
 * @version         0.1
 * @copyright       Song (c) 2011
 */  
class Debug
{
    /**
     * Buffer
     *
     * @var string
     */
    private $_buffer;
    
    /**
     * Start time
     * 
     * @var int     
     */
    private $_start = 0;
    /**
     * Instance
     *
     * @var object
     */
    private static $_instance;
    
    function __construct() {
        $this->_start = $this->_getMicrotime();
        $this->_buffer = array();    
    }
    
    /**
     * Get Instance
     *
     * @return object
     */   
    public static function getInstance() {
        if (!isset(self::$_instance)) {
            self::$_instance = new Debug();
        }
        return self::$_instance;
    }
    
    /**
     * Get the current time.
     *
     * @access public
     * @return float The current time
     */
    public function _getMicrotime() {
        list ( $usec, $sec ) = explode ( ' ', microtime () );
        return (( float ) $usec + ( float ) $sec);
    }
    
    /**
     * Get Buffer
     *
     * @return array
     */
    public function getBuffer() {
        return $this->_buffer;
    }
    
    /**
     * Get Memory Usage
     *
     * @return float MB
     */
    public function getMemUsage() {
        return sprintf ( '%0.3f', memory_get_usage() / 1048576) .' MB';  
    }
    
    /**
     * Output a time mark   
     *
     * @param string $label
     * @return string $package 
     * @access public
     */
    public function mark($label, $package = 'module') {
        $mark = 'Package: <strong>' . $package . '</strong>. ';
        $mark .= $label . '. <strong>&raquo;</strong> ';
        $mark .= sprintf ( 'Time %.5f', $this->_getMicrotime () - $this->_start ) . ' seconds';
        $mark .= ', ' . sprintf ( '%0.3f', memory_get_usage () / 1048576 ) . ' MB.';
        $this->_buffer[] = $mark;
        return $mark;
    }
    
    /**
     * Debug
     * draw ra khối debug.
     *
     * @return HTML content
     */
    public static function debug() {
        if(!IS_DEBUG) {
            return;
        }
        $debug = Debug::getInstance();    
        ob_start ();
        $debugHtml = '<style type="text/css">#system-debug{font-size: 9pt; margin-top:10px;color:#555555; line-height: 1.5em;} #system-debug div#sql-report strong{ color:#993333} </style><div id="system-debug" class="profiler"><h3>IN DEBUG ENVIROMENT</h3>';
                            
        #List Mark
        $debugHtml .= '<h4>Activities Information</h4> <ol>';
        $marks = $debug->getBuffer();
        for($i=0,$msize=sizeof($marks);$i<$msize;++$i) {
            $debugHtml .= '<li>' . $marks[$i] . '</li>';
        }
        $debugHtml .= '</ol><div> <h4>Memory Usage</h4>'. $debug->getMemUsage() .'</div>';
        
        #Show log SQL queries
        $newlineSQLKeywords = '/<strong>' . '(FROM|LEFT|INNER|OUTER|WHERE|SET|VALUES|ORDER|GROUP|HAVING|LIMIT|ON|AND|OR)' . '<\\/strong>/i';
        $sqlKeyword = array ('ASC', 'AS', 'ALTER', 'AND', 'AGAINST', 'BETWEEN', 'BOOLEAN', 'BY', 'COUNT', 'DESC', 'DISTINCT', 'DELETE', 'EXPLAIN', 'FOR', 'FROM', 'GROUP', 'HAVING', 'INSERT', 'INNER', 'INTO', 'IN', 'JOIN', 'LIKE', 'LIMIT', 'LEFT', 'MATCH', 'MODE', 'NOT', 'ORDER', 'OR', 'OUTER', 'ON', 'REPLACE', 'RIGHT', 'STRAIGHT_JOIN', 'SELECT', 'SET', 'TO', 'TRUNCATE', 'UPDATE', 'VALUES', 'WHERE' );
        
        $sqlReplaceKeyword = array ('<strong>ASC</strong>', '<strong>AS</strong>', '<strong>ALTER</strong>', '<strong>AND</strong>', '<strong>AGAINST</strong>', '<strong>BETWEEN</strong>', '<strong>BOOLEAN</strong>', '<strong>BY</strong>', '<strong>COUNT</strong>', '<strong>DESC</strong>', '<strong>DISTINCT</strong>', '<strong>DELETE</strong><br />', '<strong>EXPLAIN</strong>', '<strong>FOR</strong>', '<strong>FROM</strong>', '<strong>GROUP</strong>', '<strong>HAVING</strong>', '<strong>INSERT</strong>', '<strong>INNER</strong>', '<strong>INTO</strong>', '<strong>IN</strong>', '<strong>JOIN</strong>', '<strong>LIKE</strong>', '<strong>LIMIT</strong>', '<strong>LEFT</strong>', '<strong>MATCH</strong>', '<strong>MODE</strong>', '<strong>NOT</strong>', '<strong>ORDER</strong>', '<strong>OR</strong>', '<strong>OUTER</strong>', '<strong>ON</strong>', '<strong>REPLACE</strong><br />', '<strong>RIGHT</strong>', '<strong>STRAIGHT_JOIN</strong>', '<strong>SELECT</strong><br />', '<strong>SET</strong>', '<strong>TO</strong>', '<strong>TRUNCATE</strong><br />', '<strong>UPDATE</strong><br />', '<strong>VALUES</strong>', '<strong>WHERE</strong>' );
        
        // Query db
        if(class_exists('Database')) {
            $queriesLogNo = 0;
            $executeTime = 0;
            $debugHtml .= '<div id="sql-report"><h4>Queries Logged</h4><ol>';
            $queries = Database::getDBO();
            if($queries)
            {
                for($i = 0, $qsize = sizeof ( $queries ); $i < $qsize; ++ $i) {
                    $sql = str_replace ( $sqlKeyword, $sqlReplaceKeyword, $queries [$i] ['sql'] );
                    $sql = preg_replace ( '/\"([^\"])+\"/', '<font color="#ff000;">\\0</font>', $sql );
                    $sql = preg_replace ( '/\'([^\'])+\'/', '<font color="#ff000;">\\0</font>', $sql );
                    $sql = preg_replace ( $newlineSQLKeywords, '<br />&nbsp;&nbsp;\\0', $sql );
                    $debugHtml .= '<li>' . $sql . '<br />&nbsp;&nbsp;&nbsp;&nbsp;<em>Execute time: ' . $queries [$i] ['time'] . ' seconds</em></li>';
                    $executeTime += $queries [$i] ['time'];
                }
                $queriesLogNo += $qsize;
            }    
            $debugHtml .= '</ol><br />Total <strong>' . $queriesLogNo . '</strong> SQL queries logged take <em>' . $executeTime . '</em> seconds exec</h4>';
        } 
        
        // Included files        
        $debugHtml .= '<div><h4>Included files</h4><ol>';
        $files = get_included_files ();
        $size=sizeof($files);
        for($i=0;$i<$size;++$i) {
            $debugHtml .= '<li>' . $files[$i] . '</li>';
        }
        $debugHtml .= '</ol><br />Total <strong>' . $size . '</strong> included files.</div>';
        
        $debugHtml .= ob_get_clean ();
        
        return $debugHtml;
    }
}
?>
